package otherapi.poiexcel;


import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @author LiDong
 * @version 1.0.0
 * @createTime 2/19/2023 10:27 AM
 */
public class PoiMergeTest {

    private static final Logger logger = LoggerFactory.getLogger(PoiMergeTest.class);

    /**
     * @param headers      表头集合
     * @param dataMapList  内容集合
     * @param mergeColumns 合并单元格的列
     * @return Workbook
     */
    public static Workbook createExcel(String[] headers, List<Map<String, String>> dataMapList, String[] mergeColumns) {
        if (0 == headers.length) {
            return null;
        }
        /**
         * 初始化 excel 模板
         */
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = null;
        try {
            sheet = workbook.createSheet();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        /**
         * 初始化 head 填值标题行（第一行）
         */
        Row headRow = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headRow.createCell(i, Cell.CELL_TYPE_STRING);
            cell.setCellValue(headers[i]);
        }

        List<PoiModel> poiModels = new ArrayList<>();
        Iterator<Map<String, String>> iterator = dataMapList.iterator();
        // 这里1是从excel的第二行开始，第一行已经塞入标题了
        int index = 1;
        while (iterator.hasNext()) {
            Row row = sheet.createRow(index);
            // 取得当前这行的map，该map中以key，value的形式存着这一行值
            Map<String, String> map = iterator.next();
            // 循环列数，给当前行塞值
            for (int i = 0; i < headers.length; i++) {
                String old = "";
                // old存的是上一行统一位置的单元的值，第一行是最上一行了，所以从第二行开始记
                if (1 < index) {
                    old = null == poiModels.get(i) ? "" : poiModels.get(i).getContent();
                }
                String value = map.get(headers[i]);
                CellRangeAddress cra;
                // 循环需要合并的列
                for (String mergeColumn : mergeColumns) {
                    PoiModel poiModel;
                    if (1 == index) {
                        poiModel = new PoiModel();
                        poiModel.setOldContent(value);
                        poiModel.setContent(value);
                        poiModel.setRowIndex(1);
                        poiModel.setCellIndex(i);
                        poiModels.add(poiModel);
                        old = value;
                        break;
                    }
                    poiModel = poiModels.get(i);

                    int rowStartIndex = poiModel.getRowIndex();
                    int rowEndIndex = index - 1;
                    int cellIndex = poiModel.getCellIndex();
                    String content = poiModel.getContent();
                    String preOldContent = poiModels.get(0).getOldContent();
                    String preValue = map.get(headers[0]);
                    Boolean isHeaderEquals = mergeColumn.equals(headers[i]);

                    if (0 == i && isHeaderEquals && !content.equals(value)) {
                        if (rowStartIndex != rowEndIndex) {
                            cra = new CellRangeAddress(rowStartIndex, rowEndIndex, cellIndex, cellIndex);
                            sheet.addMergedRegion(cra);
                        }
                        // 重新记录该列的内容为当前内容，行标记改为当前行标记
                        poiModel.setContent(value);
                        poiModel.setRowIndex(index);
                        poiModel.setCellIndex(0);
                    } else if (0 < i && isHeaderEquals) {
                        if (!content.equals(value) || (content.equals(value) && !preOldContent.equals(preValue))) {
                            if (rowStartIndex != rowEndIndex) {
                                cra = new CellRangeAddress(rowStartIndex, rowEndIndex, cellIndex, cellIndex);
                                sheet.addMergedRegion(cra);
                            }
                            poiModels.get(i).setContent(value);
                            poiModels.get(i).setRowIndex(index);
                            poiModels.get(i).setCellIndex(i);
                        }
                    }
                    if (isHeaderEquals && index == dataMapList.size()) {
                        if (0 == i) {
                            if (content.equals(value)) {
                                cra = new CellRangeAddress(rowStartIndex, index, cellIndex, cellIndex);
                                sheet.addMergedRegion(cra);
                            }
                        } else if (0 < i) {
                            if (content.equals(value) && preOldContent.equals(preValue)) {
                                cra = new CellRangeAddress(rowStartIndex, index, cellIndex, cellIndex);
                                sheet.addMergedRegion(cra);
                            }
                        }
                    }
                }
                Cell cell = row.createCell(i, Cell.CELL_TYPE_STRING);
                cell.setCellValue(value);
                // 在每一个单元格处理完成后，把这个单元格内容设置为old内容
                poiModels.get(i).setOldContent(old);
            }
            index++;
        }
        return workbook;
    }


    @Test
    public void test() {
        String[] headers = {"表头列1", "表头列2", "表头列3", "表头列4"};
        List<Map<String, String>> list = new ArrayList<>();

        Map<String, String> map = new HashMap<>();
        map.put("表头列1", "1");
        map.put("表头列2", "2");
        map.put("表头列3", "3");
        map.put("表头列4", "4");
        list.add(map);
        map = new HashMap<>();
        map.put("表头列1", "1");
        map.put("表头列2", "2");
        map.put("表头列3", "3");
        map.put("表头列4", "4");
        list.add(map);
        map = new HashMap<>();
        map.put("表头列1", "5");
        map.put("表头列2", "6");
        map.put("表头列3", "7");
        map.put("表头列4", "8");
        list.add(map);
        map = new HashMap<>();
        map.put("表头列1", "7");
        map.put("表头列2", "8");
        map.put("表头列3", "9");
        map.put("表头列4", "10");
        list.add(map);
        map = new HashMap<>();
        map.put("表头列1", "7");
        map.put("表头列2", "8");
        map.put("表头列3", "9");
        map.put("表头列4", "10");
        list.add(map);

        String[] mergeColumns = {"表头列1", "表头列2", "表头列3", "表头列4"};
        Workbook workbook = createExcel(headers, list, mergeColumns);
        /*生成临时文件*/
        FileOutputStream out = null;
        String fileName = "Test.xlsx";
        try {
            File file = new File(fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            out = new FileOutputStream(file);
            workbook.write(out);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                out.flush();
                out.close();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

}
